/*
 * Paper.java
 *
 * Created on 16 November 2006, 18:37
 */

package org.foment.joliage3.reports;

import java.awt.Component;
import java.awt.Dimension;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author  ivan
 */
public class Paper extends javax.swing.JPanel implements java.io.Serializable{
  
  /** Creates new form Paper */
  public Paper() {
    initComponents();
    _fields = new HashMap();
    positionFields();
  }
  
  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
  private void initComponents() {
    scrollPaper = new javax.swing.JScrollPane();
    pnlPaper = new javax.swing.JPanel();

    setLayout(new java.awt.BorderLayout());

    scrollPaper.setBorder(null);
    scrollPaper.addComponentListener(new java.awt.event.ComponentAdapter() {
      public void componentResized(java.awt.event.ComponentEvent evt) {
        scrollPaperComponentResized(evt);
      }
    });

    pnlPaper.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

    pnlPaper.setBackground(new java.awt.Color(255, 255, 255));
    pnlPaper.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(153, 153, 153), 6), javax.swing.BorderFactory.createMatteBorder(0, 0, 2, 2, new java.awt.Color(102, 102, 102))), javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))));
    scrollPaper.setViewportView(pnlPaper);

    add(scrollPaper, java.awt.BorderLayout.PAGE_START);

  }// </editor-fold>//GEN-END:initComponents

  private int _width = 0;
  
  public void positionFields() {
    positionFields(false);
  }
  
  public void positionFields(boolean force) {
    int width = getSize().width - 24;
    if (width < 400) width = 400;
    if (!force && _width == width) return;
    _width = width;
        
    int height = (int)Math.round(width * Math.sqrt(2));
    
    Dimension size = new Dimension(width, height);
    
    pnlPaper.setSize(size);
    pnlPaper.setPreferredSize(size);
    pnlPaper.setMaximumSize(size);
    pnlPaper.setMinimumSize(size);
    scrollPaper.invalidate();
    scrollPaper.setPreferredSize(getSize());

    pnlPaper.removeAll();
    org.netbeans.lib.awtextra.AbsoluteLayout al = (org.netbeans.lib.awtextra.AbsoluteLayout)pnlPaper.getLayout();

    int iTop, iLeft, iWidth, iHeight;
    int iMargin = 50;
    width -= 2 * iMargin;
    height -= 2 * iMargin;
    
    for (Field field: _fields.values()) {
      iTop    = iMargin + (int)Math.round(height * field.getFieldTop());
      iLeft   = iMargin + (int)Math.round(width  * field.getFieldLeft());
      iHeight = (int)Math.round(height * (field.getFieldHeight()));
      iWidth  = (int)Math.round(width *  (field.getFieldWidth()));
      
      pnlPaper.add(field, new org.netbeans.lib.awtextra.AbsoluteConstraints(iLeft, iTop, iWidth, iHeight));
    }
    
    this.invalidate();
  }
  
  private void scrollPaperComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_scrollPaperComponentResized
    positionFields();
  }//GEN-LAST:event_scrollPaperComponentResized
  
  public static final int SINGLE_LINE_FIELD = 1;
  public static final int MULTIPLE_LINE_FIELD = 2;

  public static final int LEFT_ALIGNED_FIELD = 1;
  public static final int RIGHT_ALIGNED_FIELD = 2;
  public static final int CENTER_ALIGNED_FIELD = 3;
  
  private boolean _init = false;
  
  private class Field extends javax.swing.JScrollPane {
    public Field(Paper parent, int type, String name) {
      setName(name);

      setBorder(new javax.swing.border.LineBorder(new java.awt.Color(230, 240, 250), 1));
      
      _type = type;
      _name = name;
      _parent = parent;
      
      switch (type) {
        case SINGLE_LINE_FIELD:
          _textField = new javax.swing.JTextField();
          _textField.setBorder(null);
          setViewportView(_textField);
          break;
        case MULTIPLE_LINE_FIELD:
          _textArea = new javax.swing.JTextArea();          
          _textArea.setBorder(null);
          _textArea.setLineWrap(true);
          _textArea.setWrapStyleWord(true);
          setViewportView(_textArea);
          break;
      }
    }

    public void setValue(String value) {
      switch (_type) {
        case SINGLE_LINE_FIELD:
          _textField.setText(value);
          break;
        case MULTIPLE_LINE_FIELD:
          _textArea.setText(value);          
          break;
      }      
    }
    
    public String getValue() {
      switch (_type) {
        case SINGLE_LINE_FIELD:
          return _textField.getText();
        case MULTIPLE_LINE_FIELD:
          return _textArea.getText();
      }
      return null;
    }
    
    public void setFontSize(float size) {
      switch (_type) {
        case SINGLE_LINE_FIELD:
          _textField.setFont(_textField.getFont().deriveFont(size));
          break;
        case MULTIPLE_LINE_FIELD:
          _textArea.setFont(_textArea.getFont().deriveFont(size));
          break;
      }
    }
    
    public void setFontStyle(String style) {
      int istyle = 0;
      
      for (String cstyle: style.split(",")) {
        if (cstyle.equals("bold")) {
          istyle |= java.awt.Font.BOLD;
        } else if (cstyle.equals("italic")) {
          istyle |= java.awt.Font.ITALIC;
        }
      }
      
      
      switch (_type) {
        case SINGLE_LINE_FIELD:
          _textField.setFont(_textField.getFont().deriveFont(istyle));
          break;
        case MULTIPLE_LINE_FIELD:
          _textArea.setFont(_textArea.getFont().deriveFont(istyle));
          break;
      }
    }
    
    public void setAlignment(String align) {
      switch (_type) {
        case SINGLE_LINE_FIELD:
          if (align.equals("center"))
            _textField.setHorizontalAlignment(_textField.CENTER);
          else if (align.equals("right"))
            _textField.setHorizontalAlignment(_textField.RIGHT);
          else
            _textField.setHorizontalAlignment(_textField.LEFT);
          break;
        case MULTIPLE_LINE_FIELD:
          //_textArea.setFont(_textArea.getFont().deriveFont(style));
          break;
      }
    }
    
    public float getFieldLeft()   {  return _left;    }
    public float getFieldWidth()  {  return _width;   }
    public float getFieldTop()    {  return _top;     }
    public float getFieldHeight() {  return _height;  }
    
    public void setFieldLeft(float left)     { _left = left; }
    public void setFieldWidth(float width)   { _width = width; }
    public void setFieldTop(float top)       { _top = top; }
    public void setFieldHeight(float height) { _height = height; }
    
    private Paper _parent;
    private String _name;
    private int _type;
    private javax.swing.JTextField  _textField;
    private javax.swing.JTextArea   _textArea;
    private float _left = 0, _top = 0, _height = 0, _width = 0;
  }
  
  public java.util.HashMap<String, String> getFieldValues() {
    java.util.HashMap<String, String> result = new java.util.HashMap();
    for (String key: _fields.keySet()) {
      result.put(key, _fields.get(key).getValue());
    }
    return result;
  }
  
  public Field addField(int type, String name) {
    Field field = new Field(this, type, name);
    _fields.put(name, field);
    return field;
  }
  
  public String getFieldValue(String name) {
    return _fields.get(name).getValue();
  }
  
  public void setFieldValue(String name, String value) {
    _fields.get(name).setValue(value);
  }
  
  public void removeField(String name) {
    _fields.remove(name);
  }
  
  java.util.HashMap < String, Field > _fields;
  
  public Set<String> getFieldNames() {
    return _fields.keySet();
  }
  
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel pnlPaper;
  private javax.swing.JScrollPane scrollPaper;
  // End of variables declaration//GEN-END:variables
  
  public boolean loadFromInputStream(java.io.InputStream is) {
    try {
      DefaultHandler handler = new XMLReader(this);
      SAXParserFactory.newInstance().newSAXParser().parse(is, handler);
      this.positionFields(true);
      return true;
    } catch (IOException ex) {
      ex.printStackTrace();
    } catch (SAXException ex) {
      ex.printStackTrace();
    } catch (ParserConfigurationException ex) {
      ex.printStackTrace();
    }
    return false;
  }
  
  public boolean loadFromResource(String resourceName) {
    try {
      return loadFromInputStream(getClass().getResource(resourceName).openStream());
    } catch (IOException ex) {
      ex.printStackTrace();
    }
    return false;
  }
  
  public boolean loadFromString(String contents) {
    try {
      return loadFromInputStream(new ByteArrayInputStream(contents.getBytes("UTF-8")));
    } catch (IOException ex) {
      ex.printStackTrace();
    }
    return false;
  }
  
  public boolean loadFromFile(String fileName) {
    try {
      FileInputStream file = new FileInputStream(fileName);
      return loadFromInputStream(file);
    } catch (FileNotFoundException ex) {
      ex.printStackTrace();
    }
    return false;
  }
  
  private class XMLReader extends DefaultHandler {
    private Paper _paper;
    private Paper.Field _field;
    private boolean _value;
    
    public XMLReader(Paper paper) {
      _paper = paper;
      _value = false;
    }
    
    public void startDocument() throws SAXException {
      _field = null;
    }

    public void endDocument() throws SAXException {
      _field = null;
    }

    public void startElement(String namespaceURI,
      String sName, // simple name (localName)
      String qName, // qualified name
      Attributes attrs
    ) throws SAXException {
      if (qName.equals("field")) {
        String attrMultiline = attrs.getValue("multiline");
        String attrName      = attrs.getValue("name");

        int multiline;

        if (attrMultiline == null || attrMultiline.equals("no"))
          multiline = Paper.SINGLE_LINE_FIELD;
        else
          multiline = Paper.MULTIPLE_LINE_FIELD;
        
        _field = _paper.addField(multiline, attrName);
        
        if (attrs.getIndex("left") != -1)
          _field.setFieldLeft(Float.parseFloat(attrs.getValue("left")));
        
        if (attrs.getIndex("width") != -1)
          _field.setFieldWidth(Float.parseFloat(attrs.getValue("width")));
        
        if (attrs.getIndex("top") != -1)
          _field.setFieldTop(Float.parseFloat(attrs.getValue("top")));
        
        if (attrs.getIndex("height") != -1)
          _field.setFieldHeight(Float.parseFloat(attrs.getValue("height")));

      } else if (qName.equals("format")) {
        if (_field == null) return;
        
        if (attrs.getIndex("fontSize") != -1)
          _field.setFontSize(Float.parseFloat(attrs.getValue("fontSize")));
        
        if (attrs.getIndex("fontStyle") != -1)
          _field.setFontStyle(attrs.getValue("fontStyle"));
        
        if (attrs.getIndex("textAlign") != -1)
          _field.setAlignment(attrs.getValue("textAlign"));
        
      } else if (qName.equals("br")) {
        if (_value)
          _field.setValue(_field.getValue() + "\n");
      } else if (qName.equals("value")) {
        _value = true;
      }
    }

    public void endElement(String namespaceURI,
      String sName, // simple name
      String qName  // qualified name
    ) throws SAXException {
      if (qName.equals("field"))
        _field = null;
      else if (qName.equals("value"))
        _value = false;
    }

    public void characters(char buf[], int offset, int len) throws SAXException {
      if (_field != null && _value) {
        String buffer = new String(buf, offset, len);
        buffer = buffer.replace('\n', ' ');
        
        buffer = _field.getValue() + buffer;
        buffer = java.util.regex.Pattern.compile("[ \t]+").matcher(buffer).replaceAll(" ");
        _field.setValue(buffer);
      }
    }
    
  }
  
}
